package com.xzx.paymentdemo.controller;

import com.google.gson.Gson;
import com.xzx.paymentdemo.service.WxPayService;
import com.xzx.paymentdemo.util.HttpUtils;
import com.xzx.paymentdemo.util.NotificationHandlerUtils;
import com.xzx.paymentdemo.vo.R;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * wxpay
 *
 * @author xzx
 * @since 2022/8/11
 */
@CrossOrigin //跨域
@RestController
@RequestMapping("/api/wx-pay")
@Api(tags = "网站微信支付APIv3")
@Slf4j
public class WxPayController {


    @Resource
    private WxPayService wxPayService;
    @Resource
    private NotificationHandlerUtils notificationHandlerUtils;

    @ApiOperation("调用统一下单API，生成支付二维码")
    @PostMapping("/native/{productId}")
    public R nativePay(@PathVariable Long productId) {
        log.info("发起支付请求 v3");

        //返回支付二维码连接和订单号
        Map<String, Object> map = null;
        try {
            map = wxPayService.nativePay(productId);
        } catch (IOException e) {
            e.printStackTrace();
        }

        return R.ok().setData(map);
    }

    @PostMapping("/native/notify")
    public String nativeNotify(HttpServletRequest request, HttpServletResponse response) {

        Gson gson = new Gson();
        Map<String, String> map = new HashMap<>();//应答对象
        //处理通知参数，将请求体转换为字符串
        try {
            String body = HttpUtils.readData(request);
            log.info("支付通知的完整数据 ===> {}", body);
            //验签和解析请求体并解密报文
            String decryptData = notificationHandlerUtils.getDecryptData(request, body);
            log.info("支付通知解密完的数据 ===> {}", decryptData);

            //对订单进行处理
            wxPayService.processOrder(decryptData);

            response.setStatus(200);
            map.put("code", "SUCCESS");
            map.put("message", "成功");
            return gson.toJson(map);
        } catch (Exception e) {
            e.printStackTrace();
            response.setStatus(500);
            map.put("code", "ERROR");
            map.put("message", "失败");
            return gson.toJson(map);
        }
    }

    @ApiOperation("用户取消订单")
    @PostMapping("/cancel/{orderNo}")
    public R cancel(@PathVariable String orderNo) throws IOException {
        log.info("取消订单");
        wxPayService.cancelOrder(orderNo);
        return R.ok().setMessage("订单已取消");
    }

    @ApiOperation("查询订单：测试订单状态用")
    @GetMapping("query/{orderNo}")
    public R queryOrder(@PathVariable String orderNo) throws Exception {
        log.info("查询订单");
        String bodyAsString = wxPayService.queryOrder(orderNo);
        return R.ok().setMessage("查询成功").data("bodyAsString", bodyAsString);
    }

    @ApiOperation("申请退款")
    @PostMapping("/refunds/{orderNo}/{reason}")
    public R refunds(@PathVariable String orderNo, @PathVariable String reason) throws Exception {
        log.info("申请退款");
        wxPayService.refund(orderNo, reason);
        return R.ok();
    }

    @ApiOperation("查询退款：测试用")
    @GetMapping("/query-refund/{refundNo}")
    public R queryRefund(@PathVariable String refundNo) throws Exception {
        log.info("查询退款");
        String result = wxPayService.queryRefund(refundNo);
        return R.ok().setMessage("查询成功").data("result", result);
    }

    /**
     * 退款结果通知
     * 退款状态改变后，微信会把相关退款结果发送给商户
     */
    @PostMapping("/refunds/notify")
    public String refundsNotify(HttpServletRequest request, HttpServletResponse response) throws Exception {
        log.info("退款通知执行");
        Gson gson = new Gson();
        Map<String, String> map = new HashMap<>();//应答对象
        //处理通知参数，将请求体转换为字符串
        try {
            String body = HttpUtils.readData(request);
            log.info("退款通知的完整数据 ===> {}", body);
            //验签和解析请求体并解密报文
            String decryptData = notificationHandlerUtils.getDecryptData(request, body);
            log.info("退款通知解密完的数据 ===> {}", decryptData);

            //对订单进行处理
            wxPayService.processRefund(decryptData);

            response.setStatus(200);
            map.put("code", "SUCCESS");
            map.put("message", "成功");
            return gson.toJson(map);
        } catch (Exception e) {
            e.printStackTrace();
            response.setStatus(500);
            map.put("code", "ERROR");
            map.put("message", "失败");
            return gson.toJson(map);
        }
    }

    @ApiOperation("获取账单url：测试用")
    @GetMapping("/querybill/{billDate}/{type}")
    public R queryTradeBill(@PathVariable String billDate, @PathVariable String type) throws Exception {
        log.info("获取账单url");
        String downloadUrl = wxPayService.queryBill(billDate, type);
        return R.ok().setMessage("获取账单成功").data("downloadUrl", downloadUrl);
    }

    @ApiOperation("下载账单")
    @GetMapping("/downloadbill/{billDate}/{type}")
    public R downloadBill(@PathVariable String billDate, @PathVariable String type) throws Exception{
        log.info("下载订单");
        String result = wxPayService.downloadBill(billDate, type);
        return R.ok().data("result", result);
    }

}
